package cn.loioi.activiti;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

/**
 * 比较好点的一个流程demo，但是任务变量还没有使用
 * @file_name :UnitTest2.java
 * @author :loioi.cn
 * @创建时间 :2016年11月6日 上午12:42:21
 */
public class UnitTest2 {
	private final Logger logger = LoggerFactory.getLogger(UnitTest.class);

	@Test
	public void processTests() throws IOException {
		// 加载配置文件
		ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration().buildProcessEngine();
		// 取得 Activiti 服务
		RepositoryService repositoryService = processEngine.getRepositoryService();
		IdentityService identityService = processEngine.getIdentityService();
		RuntimeService runtimeService = processEngine.getRuntimeService();
		TaskService taskService = processEngine.getTaskService();
		HistoryService historyService = processEngine.getHistoryService();
		// 部署流程定义
		Deployment deploy = repositoryService.createDeployment().addClasspathResource("cn/loioi/bpmn/interview.bpmn").deploy();
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
		logger.debug("已部署流程：" + processDefinition.getKey());

		// 启动流程实例
		Map<String, Object> var = new HashMap<>();
		var.put("examineUser", "wm");
		var.put("applyUser", "wq");
		var.put("applyDepartment", "wq");
		var.put("applyTime", "2016-01-12 12:23");
		var.put("applyParam", "{a:1}");
		identityService.setAuthenticatedUserId("wq");// 设置该流程所有者
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey(), "请假", var);
		logger.debug("流程信息:pid=" + processInstance.getId() + ",pdid=" + processInstance.getProcessDefinitionId());
		process(taskService);// 查询流程进度
		// 审核
		examine(taskService, false);// 审核申请,让不通过
		process(taskService);// 查询流程进度
		// 重新提交
		Task task = taskService.createTaskQuery().taskCandidateOrAssigned("wq").singleResult();
		logger.debug("wq 的当前任务:" + task);
		if (task != null) {
			Map<String, Object> var1 = new HashMap<>();
			var1.put("applyUser", "wq");
			var1.put("applyDepartment", "wq");
			var1.put("applyTime", "2016-01-12 12:23");
			var1.put("applyParam", "{a:1}");
			var1.put("repeatApply", "true");
			taskService.complete(task.getId(), var1);
		}
		process(taskService);// 查询流程进度
		// 重新审核
		examine(taskService, true);// 再次审核申请
		process(taskService);// 查询流程进度
		// 验证已结束流程
		long count = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processDefinition.getKey()).finished().count();
		logger.debug("history process:" + count);
	}

	/**
	 * 审核申请
	 * @param taskService
	 * @param approve
	 */
	private void examine(TaskService taskService, boolean approve) {
		Task task = taskService.createTaskQuery().taskCandidateOrAssigned("wm").singleResult();
		logger.debug("wm 的当前任务:" + task);
		if (task == null) return;
		logger.debug("Process Variables ->" + JSON.toJSONString(taskService.getVariables(task.getId())));
		Map<String, Object> var1 = new HashMap<>();
		var1.put("approve", String.valueOf(approve));
		taskService.complete(task.getId(), var1);
	}

	/**
	 * 查询流程进度
	 * @param taskService
	 */
	private void process(TaskService taskService) {
		Task task = taskService.createTaskQuery().processVariableValueEquals("applyUser", "wq").singleResult();
		logger.debug("当前任务进度({}):{}", task.getAssignee(), task);
	}
}
